package net.sf.midollo.net.protocol.tunnel;

import net.sf.midollo.io.IOStreamFactory;
import net.sf.midollo.io.log.LogIOStreamFactory;
import net.sf.midollo.io.printable.PrintableOutputStream;
import net.sf.midollo.io.system.SystemIOStreamFactory;
import net.sf.midollo.net.io.SocketIOStreamFactory;
import net.sf.midollo.net.server.AsyncAcceptHandler;
import net.sf.midollo.net.server.InetServer;
import net.sf.midollo.utils.Utils;

public class Main {

  public static void main(String[] args) {

    try {

      String strLocalPort = null;
      String strRemoteAddr = null;
      String strServerLog = null;

      for (int idx = 0; idx < args.length; ++idx) {
        if (args[idx].compareTo("-p") == 0) {
          if (++idx < args.length)
            strLocalPort = args[idx];
        } else if (args[idx].compareTo("-r") == 0) {
          if (++idx < args.length)
            strRemoteAddr = args[idx];
        } else if (args[idx].compareTo("-slog") == 0) {
          if (++idx < args.length)
            strServerLog = args[idx];
        }
      }

      int localPort = Utils.parseInt(strLocalPort, 0);

      IOStreamFactory ioStreamFactory = null;

      if (strRemoteAddr != null) {
        Object[] parsedRemoteAddr = Utils.parseHostAndPort(strRemoteAddr);
        String host = Utils.getParsedHost(parsedRemoteAddr, "127.0.0.1");
        int port = Utils.getParsedPort(parsedRemoteAddr, 80);
        ioStreamFactory = new SocketIOStreamFactory(host, port);
        if (strServerLog != null) {
          PrintableOutputStream printableOutputStream = new PrintableOutputStream(System.out);
          ioStreamFactory = new LogIOStreamFactory(ioStreamFactory, printableOutputStream, null);
        }
      } else {
        ioStreamFactory = new SystemIOStreamFactory();
      }

      TunnelFactory protocolFactory = new TunnelFactory(ioStreamFactory);
      AsyncAcceptHandler acceptHandler = new AsyncAcceptHandler(protocolFactory);
      InetServer inetServer = new InetServer(localPort, acceptHandler);
      inetServer.run();

    } catch (Throwable ex) {
      ex.printStackTrace();
    }
  }
}
